package com.unicdata.ai.demo_2af.common.config;

import com.unicdata.ai.demo_2af.common.entity.User;
import com.unicdata.ai.demo_2af.service.UserService;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.LockedAccountException;
import org.apache.shiro.authc.credential.CredentialsMatcher;

import java.util.Date;

/**
 * 限制登录失败次数的凭证匹配器
 *
 * @author lhn
 * @date 2025/06/25 16:50
 * @since 1.0.0
 **/
public class LimitRetryCredentialsMatcher implements CredentialsMatcher {

    /**
     * 真正的凭证匹配器
     */
    private final CredentialsMatcher credentialsMatcher;

    /**
     * 用户服务
     */
    private final UserService userService;

    /**
     * 登录失败重试次数上限
     */
    private final int retryLimit;

    /**
     * 锁定时间(分钟)
     */
    private final int lockTime;

    public LimitRetryCredentialsMatcher(CredentialsMatcher credentialsMatcher,
                                        UserService userService,
                                        int retryLimit,
                                        int lockTime) {
        this.credentialsMatcher = credentialsMatcher;
        this.userService = userService;
        this.retryLimit = retryLimit;
        this.lockTime = lockTime;
    }

    @Override
    public boolean doCredentialsMatch(AuthenticationToken token, AuthenticationInfo info) {
        String username = (String) token.getPrincipal();
        User user = userService.getUserByUsername(username);

        // 如果已经被锁定，直接返回匹配失败
        if (user != null && user.getIsLocked() != null && user.getIsLocked() == 1) {
            throw new LockedAccountException("账号已被锁定");
        }

        // 调用真正的凭证匹配器进行匹配
        boolean matches = credentialsMatcher.doCredentialsMatch(token, info);

        if (matches) {
            // 如果匹配成功，重置登录失败次数
            if (user != null && user.getLoginFailCount() != null && user.getLoginFailCount() > 0) {
                user.setLoginFailCount(0);
                user.setLastLoginTime(new Date());
                userService.updateById(user);
            }
        } else {
            // 匹配失败，增加失败次数
            if (user != null) {
                int failCount = user.getLoginFailCount() == null ? 0 : user.getLoginFailCount();
                failCount++;
                user.setLoginFailCount(failCount);

                // 如果达到失败次数上限，锁定账号
                if (failCount >= retryLimit) {
                    user.setIsLocked(1);
                    user.setLockedTime(new Date());
                }

                userService.updateById(user);
            }
        }

        return matches;
    }
}